import React, {
    useState, forwardRef, useImperativeHandle, useEffect,
} from "react";
import {
    Form, Input, Select, Button, Space,
    Popconfirm, Cascader, DatePicker,
    message, Spin, Radio, Checkbox, Row, Col,
    Popover,
} from 'antd';
import Upload from '@/components/Upload';
import DeleteOutlined from '@ant-design/icons/DeleteOutlined';
import debounce from 'lodash/debounce';
import { localGet, localSet } from "@/utils/util";
import { adminUserAll } from '@/api/modules/adminUser';
import { ColumnsType } from '../index';

import "./index.less";

interface Props {
    tableName?: string;
    formRef?: any;
    actionRef?: any;
	columns: ColumnsType[];
    onSearch?: any;
    hideScheme?: any;
    hideSeach?: any;
}

const MoneyRange = (props: any) => {
    const { onChange } = props;
    const [, setState]: any[] = useState([]);
    
    const onInputChange1 = (e: any) => {
        setState((pre: any) => {
            const newState = [e.target.value, pre[1]];
            onChange(newState);
            return newState;
        });
    };
    const onInputChange2 = (e: any) => {
        setState((pre: any) => {
            const newState = [pre[0], e.target.value];
            onChange(newState);
            return newState;
        });
    };

    return (
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <Input onChange={onInputChange1} type="number" placeholder="低" />
            <span style={{ margin: '0 8px' }}>-</span>
            <Input onChange={onInputChange2} width={80} type="number" placeholder="高" />
        </div>
    );
};
const UserOptions = (props: any) => {
    const [loading, setLoading] = useState(false);
    const [options, setOptions] = useState(props.options || []);

    const fetchData = debounce((keyword?: any) => {
        setLoading(true);
        adminUserAll({ keyword })
        .then((res) => {
            const { data }: any = res;
            const newOptions = data.map((item: any) => ({
                label: item.nick_name,
                value: item.id,
            }));
            setOptions(newOptions);
        }).finally(() => {
            setLoading(false);
        })
    }, 200);

    const dropdownRender = (menu: any) => {
        if (loading) return <div style={{ padding: 8 }}><Spin spinning /></div>;
        return menu;
    };
    const onFocus = () => {
        if (!options || !options.length) {
            fetchData();
        }
    };
    const filterOption = (searchText: any, data: any) => {
        return data.label.includes(searchText) || String(data.value).includes(searchText);
    };
    
    return (
        <Select
            {...props}
            showSearch
            filterOption={filterOption}
            // onSearch={fetchData}
            placeholder={props.placeholder || '请选择人员'}
            options={options}
            dropdownRender={dropdownRender}
            onFocus={onFocus}
        />
    )
};
const CheckBoxItem = (props: any) => {
    const { item } = props;
    const newChild = (item.child || []);
    const newChildV = (newChild[0] || {}).option_id;
    const [checkEd, setCheckEd] = useState(false);
    const [value, setValue] = useState(undefined);
    const [label, setLabel] = useState(undefined);
    const newValue = newChildV || item.value;

    const onRadioChange = (e: any) => {
        setCheckEd(true);
        const newV = e.target.value;
        setValue(newV);
        setLabel(newV.split('_')[2]);
        props.onChange([item.id], newV);
    };
    const onCheckBoxChange = (e: any) => {
        if (e.target.checked) {
            setCheckEd(true);
            setValue(e.target.value);
            props.onChange([item.id], e.target.value);
        } else {
            setCheckEd(false);
            setValue(undefined);
            props.onChange([item.id, ...newChild.map((item: any) => item.id)], undefined);
        }
    };

    useEffect(() => {
        if (props.value && props.value.length) {
            if (props.value.some((iiitem: any) => newChild.some((iitem: any) => {
                const is = iitem.option_id === iiitem;
                is && (setValue(iiitem), setLabel(iitem.name));
                return is;
            }))) {
                setCheckEd(true);
            }
        }
    }, []);

    return (
        <Checkbox onChange={onCheckBoxChange} value={newValue} checked={checkEd}>
            {
                newChild.length ? (
                    <Popover
                        placement="top"
                        content={(
                            <Radio.Group value={value} onChange={onRadioChange}>
                                <Space direction="vertical">
                                    {newChild.map((iitem: any) => {
                                        return <Radio key={iitem.option_id} value={iitem.option_id}>{iitem.name}</Radio>
                                    })}
                                </Space>
                            </Radio.Group>
                        )}
                    >
                        {label || item.label}
                    </Popover>
                ) : item.label
            }
        </Checkbox>
    );
};
const CheckboxChildren = (props: any) => {
    const { value, onChange, options } = props;
    const [, setSelectMap] = useState({});
    const onCheckBoxChange = (...args: any) => {
        setSelectMap((pre) => {
            const newSelectMap = {
                ...pre,
                ...args[0].reduce((init: any, item: any) => ({ ...init, [item]: args[1] }), {}),
            };
            onChange(Object.values(newSelectMap).filter((item: any) => !!item));
            return newSelectMap
        })
    };

    useEffect(() => {
        if (value && value.length) {
            setSelectMap(value.reduce((init: any, item: any) => ({
                ...init,
                [item.split('_')[1]]: item,
            }), {}));
        } else {
            setSelectMap({});
        }
    }, [value]);

    return (
        <Row gutter={[0, 48]}>
            {options.map((item: any) => {
                return (
                    <Col span={4} key={item.value}>
                        <CheckBoxItem
                            key={item.value}
                            {...props}
                            item={item}
                            onChange={onCheckBoxChange}
                        />
                    </Col>
                )
            })}
        </Row>
    )
};

export const InnerComp = (props: any) => {
    const {
        formProps = {}, valueEnum = () => ({}), onChange, outerChange,
        value, placeholder, options,
        defaultValue,
    } = props;
    const newOptions = Object.keys(valueEnum()).reduce((init: any, item) => {
        init.push({
            label: valueEnum()[item].text,
            value: item,
        });
        return init;
    }, []);
    const newOnChange = (...args: any) => {
        onChange(...args);
        outerChange && outerChange(...args);
    };
    const baseProps = {
        value,
        onChange: newOnChange,
        allowClear: true,
        options: options || newOptions,
        autoCapitalize: 'off',
        autoComplete: 'off',
    };
    const extProps =  {
        defaultValue
    };
    const commonProps = {
        ...formProps,
        ...baseProps,
        placeholder: placeholder || formProps.placeholder
    };
    let Comp;
    switch (props.valueType) {
        case 'text':
            Comp = (
                <Input
                    {...commonProps}
                    type="text"
                    placeholder={commonProps.placeholder || '请输入'}
                />
            );
            break;
        case 'textarea':
            Comp = (
                <Input.TextArea
                    {...commonProps}
                    placeholder={commonProps.placeholder || '请输入'}
                />
            );
            break;
        case 'search':
            Comp = (
                <Input.Search
                    {...commonProps}
                    placeholder={commonProps.placeholder || '请输入'}
                />
            );
            break;
        case 'password':
            Comp = (
                <Input
                    {...commonProps}
                    type="password"
                    placeholder={formProps.placeholder || '请输入'}
                />
            )
            break;
        case 'money':
            Comp = <Input type="number" {...commonProps} placeholder={commonProps.placeholder || '请输入'} />;
            break;
        case 'number':
            Comp = <Input type="number" {...commonProps} placeholder={commonProps.placeholder || '请输入'} />;
            break;
        case 'dateRange':
            Comp = <DatePicker.RangePicker {...commonProps} />
            break;
        case 'date':
        case 'datetime':
        case 'time':
        case 'month':
            Comp = <DatePicker
                {...commonProps}
                picker={props.valueType}
            />
            break;
        case 'select':
            Comp = (
                <Select
                    {...commonProps}
                    placeholder={commonProps.placeholder || '请选择'}
                />
            );
            break;
        case 'cascader':
            Comp = (
                <Cascader
                    {...commonProps}
                    placeholder={commonProps.placeholder || '请选择'}
                />
            );
            break;
        case 'moneyRange':
            Comp = (<MoneyRange {...commonProps} />);
            break;
        case 'user':
            Comp = (
                <UserOptions
                    {...commonProps}
                />
            );
            break;
        case 'radio':
            Comp = (
                <Radio.Group {...commonProps}>
                    {commonProps.options.map((item: any) => (
                        <Radio key={item.value} value={item.value}>{item.label}</Radio>
                    ))}
                </Radio.Group>
            );
            break;
        case 'checkbox':
            Comp = (
                <Checkbox.Group
                    {...commonProps}
                    options={undefined}
                    style={{ ...(commonProps.style || {}), width: '100%' }}
                >
                    <Row gutter={[0, 48]}>
                        {options.map((item: any) => (
                            <Col span={4} key={item.value}>
                                <Checkbox value={item.value}>{item.label}</Checkbox>
                            </Col>
                        ))}
                    </Row>
                </Checkbox.Group>
            );
            break;
        case 'checkboxChildren':
            Comp = (
                <CheckboxChildren {...commonProps} />
            );
            break;
        case 'upload':
            Comp = (
                <Upload {...commonProps} {...extProps} />
            );
            break;
        default:
            Comp = '自己写吧';
            break;
    }
    return (
        <>{Comp}</>
    );
};

const SchemeComp = (props: any) => {
    const { form, tableName } = props;
    const [schemeList, setSchemeList]: any = useState([]);

    const onDelScheme = (e: any, i: any) => {
        setSchemeList((pre: any) => {
            const newSchemeList = pre.filter((item: any, ii: any) => i !== ii);
            localSet(`${tableName}Scheme`, [...newSchemeList]);
            return setSchemeListFunc([...newSchemeList], false);
        });
        return e.stopPropagation();
    };
    const onSelectScheme = (...args: any) => {
        if (args[1] && args[1].formV) {
            const { schemeName, scheme, ...otherFormV } = form.getFieldsValue();
            const initV = Object.keys(otherFormV).reduce((init: any, item: any) => ({ ...init, [item]: undefined }), {});
            console.log(schemeName, scheme, '12');
            form.setFieldsValue({ ...initV, ...args[1].formV });
            message.success('方案切换成功！');
        }
    };
    const setSchemeListFunc = (list: any, is: any) => {
        const newList = list.map((item: any, index: any) => ({
            ...item,
            label: (
                <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                    {item.schemeName}
                    <DeleteOutlined className="scheme-actions" onClick={(e) => onDelScheme(e, index)} />
                </div>
            ),
            value: item.schemeName,
        }));
        if (is) {
            return setSchemeList(newList);
        }
        return newList;
    };
    const onSchemeSave = () => {
        const { schemeName, scheme, ...otherFormV } = form.getFieldsValue();
        const LScheme = localGet(`${tableName}Scheme`) || [];
        if (schemeName) {
            if (!(LScheme && LScheme.length && LScheme.some((item: any) => item.schemeName === schemeName))) {
                const strageObj = { schemeName, formV: { ...otherFormV }, scheme };
                message.success('方案保存成功！');
                localSet(`${tableName}Scheme`, [...LScheme, strageObj]);
                setSchemeListFunc([...LScheme, strageObj], true);
                form.setFieldsValue({ schemeName: undefined });
            } else {
                message.warning('方案名称重复！');
            }
        } else {
            message.warning('方案名称不能为空！');
        }
    };

    useEffect(() => {
        const scheme = localGet(`${tableName}Scheme`) || [];
        setSchemeListFunc(scheme, true);
    }, []);

    return (
        <>
            <Form.Item label="" name="scheme" style={{ marginLeft: '8px' }}>
                <Select
                    options={schemeList}
                    allowClear
                    placeholder="快速查询"
                    onSelect={onSelectScheme}
                />
            </Form.Item>
            <Popconfirm
                icon={null}
                trigger="click"
                title="确定保存当前的查询条件为方案吗？"
                description={(
                    <Form.Item name="schemeName" style={{ marginBottom: 0  }}>
                        <Input placeholder="方案名称" />
                    </Form.Item>
                )}
                onConfirm={onSchemeSave}
            >
                <Button type="primary" style={{ marginBottom: '12px' }}>新增方案</Button>
            </Popconfirm>
        </>
    )
};

const Comp = forwardRef((props: Props, ref) => {
    const {
        columns: propsColumns, tableName, onSearch: propsSearch = () => {},
        hideScheme, hideSeach
    } = props;
    const [form] = Form.useForm();
    const [columns, setColumns] = useState(propsColumns || []);

    const handleReset = () => {
        form.resetFields();
    };
    const onSearch = () => {
        form.validateFields().then((res) => {
            propsSearch(res);
        });
    };
    (window as any).searchForm = form;

    useEffect(() => {
        setColumns(propsColumns);
    }, [propsColumns]);
        
    useImperativeHandle(ref, () => ({
        ...form,
    }));

    return (
        <div className="search fold">
            <Form form={form} layout="inline" onValuesChange={(!hideSeach ? undefined : setTimeout(onSearch, 16.66) as any)}>
                {
                    columns.map((column, index) => (
                        <Form.Item
                            className={`my-${column.valueType}`}
                            name={column.dataIndex} key={index}
                            label={(column.title)  as any}
                        >
                            <InnerComp {...column} outerChange={column.onChange} />
                        </Form.Item>
                    ))
                }
                { !hideSeach ? <Button style={{ marginRight: '8px' }} onClick={onSearch} type="primary">搜索</Button> : '' }
                <Button onClick={handleReset}>重置</Button>
                { !hideScheme ? <SchemeComp tableName={tableName} form={form} /> : '' }
            </Form>
        </div>
    );
});

Comp.displayName = 'SearchComp';

export default Comp;